/*
 * @copyright 2010 Gerald Jacobson
 * @license GNU General Public License
 * 
 * This file is part of Descent Assistant.
 *
 * Descent Assistant is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Descent Assistant is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Descent Assistant.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.amphiprion.descenttool.view;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.amphiprion.descenttool.Home;
import org.amphiprion.descenttool.R;
import org.amphiprion.descenttool.control.ControlerState;
import org.amphiprion.descenttool.control.ControlerState.ClickMode;
import org.amphiprion.descenttool.dao.MonsterDao;
import org.amphiprion.descenttool.entity.Monster;
import org.amphiprion.descenttool.util.BitmapUtil;
import org.amphiprion.descenttool.util.DeviceUtil;
import org.amphiprion.descenttool.util.PreferenceUtil;
import org.amphiprion.descenttool.util.PreferenceUtil.Preference;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.EditText;
import android.widget.Toast;

/**
 * @author Amphiprion
 * 
 */
public class EncounterView extends View {
	public volatile boolean drawing = false;
	private int editingIndex = -1;
	private float dpiScale = 1;
	List<Monster> monsters = new ArrayList<Monster>();

	Bitmap background;
	Rect backgroundSrc;
	Rect backgroundDest;

	Bitmap board;
	Bitmap unknown;

	Bitmap downArrow;
	Bitmap upArrow;
	Bitmap editStat;
	Bitmap magic;
	Bitmap melee;
	Bitmap range;
	Bitmap morph;
	Bitmap diceWhite;
	Bitmap diceBlue;
	Bitmap diceRed;
	Bitmap diceGreen;
	Bitmap diceYellow;
	Bitmap diceBlack;
	Bitmap diceSilver;
	Bitmap diceGold;
	Bitmap diceMorph;

	Bitmap destroy;
	Bitmap reinit;
	Bitmap addMonster;
	Bitmap help;
	String helpLabel;
	Bitmap pref;

	Bitmap copyMaster;
	Bitmap copyNormal;
	Bitmap copyToMaster;
	Bitmap copyToNormal;
	private Point copyPoint = new Point();
	private Point copyToPoint = new Point();
	private Point namePoint = new Point();

	Paint paint;
	Paint paintTitle;
	Paint paintStat;
	Paint paintBackSkill;
	Paint paintLineSkill;
	Paint paintBackDice;

	int offset = 0;
	int translate = 0;
	private long lastTouchedTimer = 0;
	private DecelerateInterpolator decelerate = new DecelerateInterpolator();
	private int lastTouchedTranslate;

	// private Point editingPoint = new Point();
	private Point[] movePoints = new Point[] { new Point(), new Point(), new Point() };
	private Point[] healthPoints = new Point[] { new Point(), new Point(), new Point() };
	private Point[] armorPoints = new Point[] { new Point(), new Point(), new Point() };

	public EncounterView(Context context) {
		super(context);
		init();
	}

	public EncounterView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public EncounterView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	private void init() {

		DisplayMetrics metrics = new DisplayMetrics();
		((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(metrics);
		dpiScale = metrics.density * 160 / 240.0f;

		paint = new Paint();

		paintTitle = new Paint();
		paintTitle.setColor(getResources().getColor(R.color.black));
		paintTitle.setTextSize(18);
		paintTitle.setFakeBoldText(true);
		paintTitle.setAntiAlias(true);

		paintStat = new Paint();
		paintStat.setColor(getResources().getColor(R.color.black));
		paintStat.setTextSize(20);
		paintStat.setFakeBoldText(true);
		paintStat.setAntiAlias(true);

		paintBackSkill = new Paint();
		paintBackSkill.setColor(getResources().getColor(R.color.white));
		paintBackSkill.setAlpha(190);

		paintLineSkill = new Paint();

		paintBackDice = new Paint();
		paintBackDice.setColor(getResources().getColor(R.color.black));
		paintBackDice.setAlpha(180);

		background = BitmapUtil.getBitmap("background.png");
		backgroundSrc = new Rect(0, 0, background.getWidth(), background.getHeight());

		board = BitmapUtil.getBitmap("template.png");
		downArrow = BitmapUtil.getBitmap("downarrow.png");
		upArrow = BitmapUtil.getBitmap("uparrow.png");
		editStat = BitmapUtil.getBitmap("editstat.png");
		magic = BitmapUtil.getBitmap("magic.png");
		melee = BitmapUtil.getBitmap("melee.png");
		range = BitmapUtil.getBitmap("range.png");
		morph = BitmapUtil.getBitmap("morph.png");

		diceWhite = BitmapUtil.getBitmap("white_dice.png");
		diceBlue = BitmapUtil.getBitmap("blue_dice.png");
		diceRed = BitmapUtil.getBitmap("red_dice.png");
		diceGreen = BitmapUtil.getBitmap("green_dice.png");
		diceYellow = BitmapUtil.getBitmap("yellow_dice.png");
		diceBlack = BitmapUtil.getBitmap("black_dice.png");
		diceSilver = BitmapUtil.getBitmap("silver_dice.png");
		diceGold = BitmapUtil.getBitmap("gold_dice.png");
		diceMorph = BitmapUtil.getBitmap("morph_dice.png");

		destroy = BitmapUtil.getBitmap("destroy.png");
		reinit = BitmapUtil.getBitmap("reinit.png");
		addMonster = BitmapUtil.getBitmap("add_monster.png");
		help = BitmapUtil.getBitmap("help.png");
		helpLabel = "" + getResources().getText(R.string.help);
		pref = BitmapUtil.getBitmap("pref.png");
		unknown = BitmapUtil.getBitmap("unknown.png");

		copyMaster = BitmapUtil.getBitmap("copy_master.png");
		copyNormal = BitmapUtil.getBitmap("copy_normal.png");
		copyToMaster = BitmapUtil.getBitmap("copy_to_master.png");
		copyToNormal = BitmapUtil.getBitmap("copy_to_normal.png");

		offset = 0;
	}

	@Override
	protected void onDraw(Canvas canvas) {
		drawing = true;
		if (canvas.getWidth() < canvas.getHeight()) {
			dpiScale = Math.min(canvas.getWidth() / 480.0f, canvas.getHeight() / 800.0f);
		} else {
			dpiScale = Math.min(canvas.getWidth() / 800.0f, canvas.getHeight() / 480.0f);
		}
		// time++;
		backgroundDest = new Rect(0, 0, getWidth(), getHeight());

		// offset = (int) (System.currentTimeMillis() - time) / 2000;
		super.onDraw(canvas);
		canvas.drawBitmap(background, backgroundSrc, backgroundDest, paint);
		int[] indexes = new int[] { offset - 3, offset + 3, offset - 2, offset + 2, offset - 1, offset + 1, offset };
		for (int i = 0; i < indexes.length; i++) {
			int index = indexes[i];
			if (index >= 0 && index < monsters.size()) {
				int centerX = canvas.getWidth() / 2;
				int posX = centerX;
				if (translate <= 0) {
					if (index == offset) {
						posX += translate;
					} else if (index - offset == 1) {
						posX += board.getWidth() * dpiScale / 2.0f;
						posX += translate;
					} else if (index - offset == -1) {
						posX += -board.getWidth() * dpiScale / 2.0f;
						posX += translate / 2.0f;
					} else if (index - offset == 2) {
						posX += 3 * board.getWidth() * dpiScale / 4.0f;
						posX += translate / 2.0f;
					} else if (index - offset == -2) {
						posX += -3 * board.getWidth() * dpiScale / 4.0f;
						posX += translate / 4.0f;
					} else if (index - offset == 3) {
						posX += 7 * board.getWidth() * dpiScale / 8.0f;
						posX += translate / 4.0f;
					} else if (index - offset == -3) {
						continue;
					}
				} else {
					if (index == offset) {
						posX += translate;
					} else if (index - offset == -1) {
						posX += -board.getWidth() * dpiScale / 2.0f;
						posX += translate;
					} else if (index - offset == 1) {
						posX += board.getWidth() * dpiScale / 2.0f;
						posX += translate / 2.0f;
					} else if (index - offset == -2) {
						posX += -3 * board.getWidth() * dpiScale / 4.0f;
						posX += translate / 2.0f;
					} else if (index - offset == 2) {
						posX += 3 * board.getWidth() * dpiScale / 4.0f;
						posX += translate / 4.0f;
					} else if (index - offset == -3) {
						posX += -7 * board.getWidth() * dpiScale / 8.0f;
						posX += translate / 4.0f;
					} else if (index - offset == 3) {
						continue;
					}
				}
				Monster monster = monsters.get(index);

				Bitmap naga = BitmapUtil.getBitmap(monster.image + ".png");
				if (naga == null) {
					naga = BitmapUtil.getBitmap("unknown.png");
				}

				// / + (int) ((index - offset) * board.getWidth() / 2.0f);
				// posX = posX + time;
				float scale = 1.0f / (1 + Math.abs((posX - centerX) / (board.getWidth() / 2.0f)));

				Matrix m = new Matrix();
				m.postTranslate(-naga.getWidth() / 2, -naga.getHeight() / 2);
				m.postScale(scale * dpiScale, scale * dpiScale);
				// float delta = 0;
				// if (index == offset) {
				// } else if (index - offset == -1 || index - offset == +1) {
				// delta = Math.signum(index - offset) * board.getWidth() / 2;
				// } else {
				// delta = Math.signum(index - offset) * 3 * board.getWidth() /
				// 4;
				// }
				// delta =
				m.postTranslate(posX, canvas.getHeight() / 2 - 82 * dpiScale * scale);
				canvas.drawBitmap(naga, m, paint);
				if (/* translate == 0 && */index == offset) {
					paintStat.setTextSize(20 * scale * dpiScale);
					int alpha = (int) (255 * (board.getWidth() / 4.0f - Math.abs(translate)) / (board.getWidth() / 4.0f));
					paintStat.setAlpha(alpha);
					paintBackSkill.setAlpha((int) (alpha * 0.7f));
					paintLineSkill.setAlpha(alpha);
					for (int iSkill = 0; iSkill < monster.getSkills().size(); iSkill++) {
						canvas.drawRect(posX - naga.getWidth() * scale * dpiScale / 2, canvas.getHeight() / 2 - 194 * dpiScale * scale + iSkill * 32 * dpiScale * scale, posX
								+ naga.getWidth() * scale * dpiScale / 2, canvas.getHeight() / 2 - 194 * dpiScale * scale + (iSkill + 1) * 32 * dpiScale * scale - 1,
								paintBackSkill);
						canvas.drawLine(posX - naga.getWidth() * scale * dpiScale / 2, canvas.getHeight() / 2 - 194 * scale * dpiScale + (iSkill + 1) * 32 * dpiScale * scale - 1,
								posX + naga.getWidth() * scale * dpiScale / 2, canvas.getHeight() / 2 - 194 * dpiScale * scale + (iSkill + 1) * 32 * dpiScale * scale - 1,
								paintLineSkill);
						canvas.drawText(monster.getSkills().get(iSkill).parseName(), posX - naga.getWidth() * scale * dpiScale / 2 + 26 * scale * dpiScale, canvas.getHeight() / 2
								- 194 * dpiScale * scale + iSkill * 32 * dpiScale * scale + 23 * dpiScale * scale, paintStat);

					}
					// dices
					paintBackDice.setAlpha((int) (alpha * 0.7f));
					canvas.drawRect(posX - naga.getWidth() * scale * dpiScale / 2, canvas.getHeight() / 2 - 194 * dpiScale * scale + 6 * 32 * scale * dpiScale,
							posX + naga.getWidth() * scale * dpiScale / 2, canvas.getHeight() / 2 - 194 * scale * dpiScale + 7 * 32 * scale * dpiScale, paintBackDice);

					Bitmap attack;
					switch (monster.attackType) {
					case MELEE:
						attack = melee;
						break;
					case RANGE:
						attack = range;
						break;
					case MAGIC:
						attack = magic;
						break;
					default:
						attack = morph;
						break;
					}
					m = new Matrix();
					m.postTranslate(-attack.getWidth() / 2, -attack.getHeight() / 2);
					m.postScale(scale * dpiScale, scale * dpiScale);
					m.postTranslate(posX - naga.getWidth() * scale * dpiScale / 2 + 28 * dpiScale * scale, canvas.getHeight() / 2 - 193 * dpiScale * scale + 6 * 32 * dpiScale
							* scale + 15 * dpiScale * scale);
					canvas.drawBitmap(attack, m, paintLineSkill);

					int offsetDice = (int) (posX - naga.getWidth() * scale * dpiScale / 2 + 28 * dpiScale * scale + 36 * dpiScale * scale);
					offsetDice = paintDices(canvas, scale, monster.diceMorph, diceMorph, offsetDice);
					offsetDice = paintDices(canvas, scale, monster.diceWhite, diceWhite, offsetDice);
					offsetDice = paintDices(canvas, scale, monster.diceBlue, diceBlue, offsetDice);
					offsetDice = paintDices(canvas, scale, monster.diceRed, diceRed, offsetDice);
					offsetDice = paintDices(canvas, scale, monster.diceGreen, diceGreen, offsetDice);
					offsetDice = paintDices(canvas, scale, monster.diceYellow, diceYellow, offsetDice);
					offsetDice = paintDices(canvas, scale, monster.diceBlack, diceBlack, offsetDice);
					offsetDice = paintDices(canvas, scale, monster.diceSilver, diceSilver, offsetDice);
					offsetDice = paintDices(canvas, scale, monster.diceGold, diceGold, offsetDice);
				}

				m = new Matrix();
				m.postTranslate(-board.getWidth() / 2, -board.getHeight() / 2);
				m.postScale(scale * dpiScale, scale * dpiScale);
				m.postTranslate(posX, canvas.getHeight() / 2);
				canvas.drawBitmap(board, m, paint);

				String txt = monster.name;
				paintTitle.setTextSize(18 * dpiScale * scale);
				if (monster.major) {
					paintTitle.setColor(getResources().getColor(R.color.major));
				} else {
					paintTitle.setColor(getResources().getColor(R.color.black));
				}
				float txtW = paintTitle.measureText(txt);
				namePoint.x = posX;
				namePoint.y = (int) (canvas.getHeight() / 2 - 215 * dpiScale * scale);
				canvas.drawText(txt, posX - txtW / 2, canvas.getHeight() / 2 - 205 * dpiScale * scale, paintTitle);

				/*
				 * if (translate == 0 && index == offset) { editingPoint.x =
				 * posX; editingPoint.y = canvas.getHeight() / 2 + (int) (90 *
				 * dpiScale); m = new Matrix();
				 * m.postTranslate(-editStat.getWidth() / 2,
				 * -editStat.getHeight() / 2); m.postScale(scale, scale);
				 * m.postTranslate(editingPoint.x, editingPoint.y);
				 * canvas.drawBitmap(editStat, m, paint); }
				 */

				paintStat.setAlpha(255);
				paintStat.setTextSize(20 * dpiScale * scale);
				int statOffset = 0;
				Point[] addRemovePoints = null;
				for (int iStat = 0; iStat < 3; iStat++) {
					// statistique
					if (iStat == 0) {
						txt = "" + monster.getMove();
						statOffset = (int) (-85 * dpiScale);
						addRemovePoints = movePoints;
					} else if (iStat == 1) {
						txt = "" + monster.getHealth();
						statOffset = (int) (18 * dpiScale);
						addRemovePoints = healthPoints;
					} else if (iStat == 2) {
						txt = "" + monster.getArmor();
						statOffset = (int) (111 * dpiScale);
						addRemovePoints = armorPoints;
					}
					addRemovePoints[0].x = (int) (posX + statOffset * scale);
					addRemovePoints[0].y = (int) (canvas.getHeight() / 2 + 186 * dpiScale * scale);
					txtW = paintStat.measureText(txt);
					canvas.drawText(txt, addRemovePoints[0].x - txtW / 2, addRemovePoints[0].y + 5 * dpiScale, paintStat);

					// arrows
					if (editingIndex == iStat && translate == 0 && index == offset) {
						addRemovePoints[1].x = posX + statOffset - (int) (36 * dpiScale);
						addRemovePoints[1].y = canvas.getHeight() / 2 + (int) (160 * dpiScale);
						m = new Matrix();
						m.postTranslate(-upArrow.getWidth() * dpiScale / 2, -upArrow.getHeight() * dpiScale / 2);
						m.postScale(scale * dpiScale, scale * dpiScale);
						m.postTranslate(addRemovePoints[1].x, addRemovePoints[1].y);
						canvas.drawBitmap(upArrow, m, paint);

						addRemovePoints[2].x = posX + statOffset - (int) (36 * dpiScale);
						addRemovePoints[2].y = canvas.getHeight() / 2 + (int) (215 * dpiScale);
						m = new Matrix();
						m.postTranslate(-downArrow.getWidth() * dpiScale / 2, -downArrow.getHeight() * dpiScale / 2);
						m.postScale(scale * dpiScale, scale * dpiScale);
						m.postTranslate(addRemovePoints[2].x, addRemovePoints[2].y);
						canvas.drawBitmap(downArrow, m, paint);
					}
				}

				// copy
				if (translate == 0 && index == offset && monster.extend == null) {
					copyPoint.x = (int) (posX + naga.getWidth() * scale * dpiScale / 2);
					copyPoint.y = (int) (canvas.getHeight() / 2 - 130 * dpiScale * scale);
					m = new Matrix();
					m.postTranslate(-copyMaster.getWidth() / 2, -copyMaster.getHeight() / 2);
					m.postScale(scale * dpiScale, scale * dpiScale);
					m.postTranslate(copyPoint.x, copyPoint.y);
					if (monster.major) {
						canvas.drawBitmap(copyMaster, m, paint);
					} else {
						canvas.drawBitmap(copyNormal, m, paint);
					}

					copyToPoint.x = (int) (posX + naga.getWidth() * dpiScale * scale / 2);
					copyToPoint.y = (int) (canvas.getHeight() / 2 - 50 * dpiScale * scale);
					m = new Matrix();
					m.postTranslate(-copyMaster.getWidth() / 2, -copyMaster.getHeight() / 2);
					m.postScale(scale * dpiScale, scale * dpiScale);
					m.postTranslate(copyToPoint.x, copyToPoint.y);
					if (monster.major) {
						canvas.drawBitmap(copyToNormal, m, paint);
					} else {
						canvas.drawBitmap(copyToMaster, m, paint);
					}

				}
			}
		}

		if (monsters.size() > 0) {
			Matrix m = new Matrix();
			m.postTranslate(-destroy.getWidth() / 2, -destroy.getHeight() / 2);
			m.postScale(dpiScale, dpiScale);
			m.postTranslate(canvas.getWidth() - destroy.getWidth() * dpiScale / 2, canvas.getHeight() - destroy.getHeight() * dpiScale / 2);
			canvas.drawBitmap(destroy, m, paint);

			m.reset();
			m.postTranslate(-reinit.getWidth() / 2, -reinit.getHeight() / 2);
			m.postScale(dpiScale, dpiScale);
			m.postTranslate(reinit.getWidth() * dpiScale / 2, canvas.getHeight() - reinit.getHeight() * dpiScale / 2);
			canvas.drawBitmap(reinit, m, paint);

		}
		Matrix m = new Matrix();
		m.postTranslate(-addMonster.getWidth() / 2, -addMonster.getHeight() / 2);
		m.postScale(dpiScale, dpiScale);
		m.postTranslate(addMonster.getWidth() * dpiScale / 2, addMonster.getHeight() * dpiScale / 2);
		canvas.drawBitmap(addMonster, m, paint);

		m.reset();
		m.postTranslate(-help.getWidth() / 2, -help.getHeight() / 2);
		m.postScale(dpiScale, dpiScale);
		m.postTranslate(canvas.getWidth() - help.getWidth() * dpiScale / 2, help.getHeight() * dpiScale / 2);
		canvas.drawBitmap(help, m, paint);
		paintTitle.setTextSize(18 * dpiScale);
		paintTitle.setColor(getResources().getColor(R.color.black));
		int wTxt = (int) paintTitle.measureText(helpLabel);
		canvas.drawText(helpLabel, canvas.getWidth() - help.getWidth() * dpiScale / 2 - wTxt / 2, help.getHeight() * dpiScale + 10 * dpiScale, paintTitle);

		m.reset();
		m.postTranslate(-pref.getWidth() / 2, -pref.getHeight() / 2);
		m.postScale(dpiScale, dpiScale);
		m.postTranslate(canvas.getWidth() - pref.getWidth() * dpiScale / 2 - help.getWidth() * dpiScale, pref.getHeight() * dpiScale / 2);
		canvas.drawBitmap(pref, m, paint);
		paintTitle.setTextSize(18 * dpiScale);
		paintTitle.setColor(getResources().getColor(R.color.black));
		wTxt = (int) paintTitle.measureText("pref");
		canvas.drawText("pref", canvas.getWidth() - help.getWidth() * dpiScale - pref.getWidth() * dpiScale / 2 - wTxt / 2, pref.getHeight() * dpiScale + 10 * dpiScale, paintTitle);

		drawing = false;
	}

	private int paintDices(Canvas canvas, float scale, int diceCount, Bitmap dice, int offsetDice) {
		if (diceCount > 0) {
			for (int iDice = 0; iDice < diceCount; iDice++) {
				Matrix m = new Matrix();
				m.postTranslate(-dice.getWidth() / 2, -dice.getHeight() / 2);
				m.postScale(scale * dpiScale, scale * dpiScale);
				m.postTranslate(offsetDice, canvas.getHeight() / 2 - 193 * dpiScale * scale + 6 * 32 * dpiScale * scale + 15 * dpiScale * scale);
				canvas.drawBitmap(dice, m, paintStat);
				offsetDice += dice.getWidth() * dpiScale * scale + 3 * scale * dpiScale;
			}
		}
		return offsetDice;
	}

	public void onInput(ControlerState state, long elapsed) {
		if (state.touched) {

			lastTouchedTimer = System.currentTimeMillis();
			translate += state.translate.x;
			lastTouchedTranslate = translate;

			if (translate < 0) {
				int o = -(int) (translate / (board.getWidth() * dpiScale / 4.0f));
				if (o > 0) {
					if (offset < monsters.size() - 1) {
						offset += 1;
						translate = translate + (int) (o * board.getWidth() * dpiScale / 4.0f);
						translate = (int) (board.getWidth() * dpiScale / 4.0f) + translate;
					} else {
						translate = -(int) (board.getWidth() * dpiScale / 4.0f) + 1;
					}
				}
			} else if (translate > 0) {
				int o = (int) (translate / (board.getWidth() * dpiScale / 4.0f));
				if (o > 0) {
					if (offset > 0) {
						offset -= 1;
						translate = translate - (int) (o * board.getWidth() * dpiScale / 4.0f);
						translate = translate - (int) (board.getWidth() * dpiScale / 4.0f);
					} else {
						translate = (int) (board.getWidth() * dpiScale / 4.0f) - 1;
					}
				}
			} else {
				if (state.click == ClickMode.DOWN) {
					if (state.position.x > getWidth() - help.getWidth() * dpiScale && state.position.y < help.getHeight() * dpiScale) {
						showHelp();
						return;
					} else if (state.position.x > getWidth() - pref.getWidth() * dpiScale - help.getWidth() * dpiScale
							&& state.position.x < getWidth() - help.getWidth() * dpiScale && state.position.y < help.getHeight() * dpiScale) {
						((Home) getContext()).displayPreferences();
						return;
					}
				}
				int modeClick = PreferenceUtil.getInt(Preference.UPDATE_CLICK_MODE, 0);
				if (state.click == ClickMode.DOWN && modeClick == 0) {
					checkMonsterClick(state);
				}
			}

		} else {
			if (translate != 0) {
				long timer = System.currentTimeMillis();
				if (timer - lastTouchedTimer > 300) {
					translate = 0;
				} else {
					translate = (int) (decelerate.getInterpolation(1 - (timer - lastTouchedTimer) / 300.0f) * lastTouchedTranslate);
				}
			} else {
				if (state.click == ClickMode.DOUBLE_CLICK) {
					if (state.position.x > getWidth() - destroy.getWidth() * dpiScale && state.position.y > getHeight() - destroy.getHeight() * dpiScale) {
						if (monsters.size() > 0) {
							monsters.remove(offset);
							DeviceUtil.vibrate(75);
							if (offset >= monsters.size()) {
								offset = monsters.size() - 1;
							}
							return;
						}
					} else if (state.position.x < reinit.getWidth() * dpiScale && state.position.y > getHeight() - reinit.getHeight() * dpiScale) {
						if (monsters.size() > 0) {
							monsters.get(offset).reinit();
							DeviceUtil.vibrate(75);
							return;
						}
					} else if (state.position.x < addMonster.getWidth() * dpiScale && state.position.y < addMonster.getHeight() * dpiScale) {
						DeviceUtil.vibrate(75);
						((Home) getContext()).addMonsterRequested();
						return;
					}
				}

				int modeClick = PreferenceUtil.getInt(Preference.UPDATE_CLICK_MODE, 0);
				if (state.click == ClickMode.LONG_CLICK && modeClick == 1) {
					checkMonsterClick(state);
				}
			}
		}
	}

	private void checkMonsterClick(ControlerState state) {
		if (offset >= 0 && offset < monsters.size()) {
			final Monster monster = monsters.get(offset);
			if (state.position.x > getWidth() / 2 - unknown.getWidth() * dpiScale / 2 && state.position.x < getWidth() / 2 + unknown.getWidth() * dpiScale / 2
					&& state.position.y > getHeight() / 2 - 194 * dpiScale && state.position.y < getHeight() / 2 - 194 * dpiScale + 6 * 32 * dpiScale) {
				final int skillIndex = (int) ((state.position.y - (getHeight() / 2 - 194 * dpiScale)) / (32 * dpiScale));
				if (skillIndex >= 0 && skillIndex < monster.getSkills().size()) {
					((Activity) getContext()).runOnUiThread(new Runnable() {
						@Override
						public void run() {
							AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
							builder.setTitle(monster.getSkills().get(skillIndex).parseName());
							builder.setMessage(monster.getSkills().get(skillIndex).parseDescription());
							AlertDialog alert = builder.create();
							alert.show();
						}
					});

				}
			} else if (monster.extend == null && getDistance(copyPoint, state.position) < 40 * dpiScale) {
				// copy monster
				DeviceUtil.vibrate(25);
				final Monster nm = MonsterDao.getInstance().getMonster(monster.id, monster.level);
				if (nm != null) {
					monsters.add(nm);
					((Home) getContext()).runOnUiThread(new Runnable() {
						@Override
						public void run() {
							Toast.makeText(getContext(), nm.name, Toast.LENGTH_SHORT).show();
						}
					});
				}
			} else if (monster.extend == null && getDistance(copyToPoint, state.position) < 40 * dpiScale) {
				// copy to normal/major monster
				DeviceUtil.vibrate(25);
				String nmId = monster.id;
				if (monster.major) {
					nmId = nmId.substring(0, nmId.length() - 2);
				} else {
					nmId += "_m";
				}
				final Monster nm = MonsterDao.getInstance().getMonster(nmId, monster.level);
				if (nm != null) {
					monsters.add(nm);
					((Home) getContext()).runOnUiThread(new Runnable() {
						@Override
						public void run() {
							Toast.makeText(getContext(), nm.name, Toast.LENGTH_SHORT).show();
						}
					});
				}
			} else if (state.position.x > namePoint.x - unknown.getWidth() / 2 && state.position.x < namePoint.x + unknown.getWidth() / 2
					&& state.position.y > namePoint.y - 15 * dpiScale && state.position.y < namePoint.y + 15 * dpiScale) {
				DeviceUtil.vibrate(25);
				((Home) getContext()).runOnUiThread(new Runnable() {
					@Override
					public void run() {
						rename(monster);
					}
				});
			} else if (getDistance(movePoints[0], state.position) < 24 * dpiScale) {
				editingIndex = editingIndex == 0 ? -1 : 0;
				DeviceUtil.vibrate(25);
			} else if (editingIndex == 0 && getDistance(movePoints[1], state.position) < 24 * dpiScale) {
				monster.setMove(monster.getMove() + 1);
				DeviceUtil.vibrate(25);
			} else if (editingIndex == 0 && getDistance(movePoints[2], state.position) < 24 * dpiScale) {
				if (monster.getMove() > 0) {
					monster.setMove(monster.getMove() - 1);
					DeviceUtil.vibrate(25);
				}
			} else if (getDistance(healthPoints[0], state.position) < 24 * dpiScale) {
				editingIndex = editingIndex == 1 ? -1 : 1;
				DeviceUtil.vibrate(25);
			} else if (editingIndex == 1 && getDistance(healthPoints[1], state.position) < 24 * dpiScale) {
				monster.setHealth(monster.getHealth() + 1);
				DeviceUtil.vibrate(25);
			} else if (editingIndex == 1 && getDistance(healthPoints[2], state.position) < 24 * dpiScale) {
				if (monster.getHealth() > 0) {
					monster.setHealth(monster.getHealth() - 1);
					DeviceUtil.vibrate(25);
				}
			} else if (getDistance(armorPoints[0], state.position) < 24 * dpiScale) {
				editingIndex = editingIndex == 2 ? -1 : 2;
				DeviceUtil.vibrate(25);
			} else if (editingIndex == 2 && getDistance(armorPoints[1], state.position) < 24 * dpiScale) {
				monster.setArmor(monster.getArmor() + 1);
				DeviceUtil.vibrate(25);
			} else if (editingIndex == 2 && getDistance(armorPoints[2], state.position) < 24 * dpiScale) {
				if (monster.getArmor() > 0) {
					monster.setArmor(monster.getArmor() - 1);
					DeviceUtil.vibrate(25);
				}
			}
		}
	}

	private void showHelp() {
		final String helpMessage = "" + getResources().getText(R.string.help_message);
		((Activity) getContext()).runOnUiThread(new Runnable() {
			@Override
			public void run() {
				AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
				builder.setTitle(helpLabel);
				builder.setMessage(helpMessage);
				AlertDialog alert = builder.create();
				alert.show();
			}
		});
	}

	private double getDistance(Point p1, Point p2) {
		return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
	}

	private void rename(final Monster m) {
		AlertDialog.Builder alert = new AlertDialog.Builder(getContext());

		alert.setTitle(R.string.rename);
		// alert.setMessage(R.string.rename);

		// Set an EditText view to get user input
		final EditText input = new EditText(getContext());
		input.setText(m.name);
		alert.setView(input);

		alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				String value = "" + input.getText();
				m.name = value;
			}
		});

		alert.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int whichButton) {
				// Canceled.
			}
		});

		alert.show();
	}

	public void addMonster(Monster m) {
		monsters.add(m);
		offset = monsters.size() - 1;
	}

	public void saveViewData(Bundle outState) {
		outState.putSerializable("MONSTERS", (Serializable) monsters);
		outState.putInt("OFFSET", offset);
	}

	@SuppressWarnings("unchecked")
	public void restoreViewData(Bundle inState) {
		monsters = (List<Monster>) inState.getSerializable("MONSTERS");
		offset = inState.getInt("OFFSET");
	}

}
